#ifndef _PARAMETERS_H_
#define _PARAMETERS_H_


#include "headers.h"
#include "macros.h"



enum eComputingModel{
	RENDER_SINGLE_SIMULATED_COLOR,
	RENDER_SINGLE_SIMULATED_COLOR_TEMPERATURE,
	RENDER_SINGLE_SIMULATED_RESULT_COLOR,
	RENDER_SINGLE_CAPTURED_RESULT_COLOR,
	RENDER_SINGLE,
	GENERATE_SINGLE_VISUAL_HULL_SIMULATED,
	GENERATE_SINGLE_VISUAL_HULL_SIMULATED_COLOR_TEMPERATURE, 
	GENERATE_SINGLE_VISUAL_HULL_SIMULATED_COLOR_TEMPERATURE_GPU, 
	GENERATE_SINGLE_VISUAL_HULL_SIMULATED_COLOR_TEMPERATURE_GPU_OCTREE,
	GENERATE_SINGLE_VISUAL_HULL_SIMULATED_COLOR_TEMPERATURE_GPU_OCTREE_RESIZE,
	GENERATE_SINGLE_VISUAL_HULL_SIMULATED_COLOR_TEMPERATURE_GPU_OCTREE_COMPECT,
	GENERATE_SINGLE_VISUAL_HULL,
	GENERATE_MULTIPLE_VISUAL_HULL,
	RECONSTRUCT_SINGLE_SIMULATED_COLOR,
	RECONSTRUCT_SINGLE_SIMULATED_COLOR_TEMPERATURE,
	GENERATE_SINGLE_VISUAL_HULL_SIMULATED_TEMPERATURE,
	RENDER_SINGLE_SIMULATED_TEMPERATURE,
	RECONSTRUCT_SINGLE_SIMULATED_TEMPERATURE,
	RENDER_SINGLE_SIMULATED_RESULT_TEMPERATURE,
	RECONSTRUCT_MULTIPLE,
	RECONSTRUCT_SINGLE_CAPTURED_COLOR,
	ALGEBRAIC_RECONSTRUCTION_SINGLE_SIMULATED,

	RENDER_CT_IMAGE,
	GENERATE_CT_VISUAL_HULL,
	RECONSTRUCT_CT,

	GENERATE_VISUAL_HULL_MIXING_FLUID,
	RECONSTRUCT_MIXING_FLUID,

	RECONSTRUCT_SINGLE_CAPTURED_TEMPERATURE, 
	RENDER_SINGLE_CAPTURED_RESULT_TEMPERATURE,

	RENDER_MULTIPLE_SMOKE,

	GENERATE_SMOKE_VISUAL_HULL,
	RECONSTRUCT_SMOKE,
	RENDER_SMOKE_RESULT
};


extern eComputingModel gComputingModel;
extern int Model_type;

extern int gSamplingMaxSteps;
extern float gSamplingStep;

extern int gChannel;

extern const char *gOriginal[];
extern const char *gReference[];

extern const char *gSDKsample;
extern const char *gVolumeFilename;
extern uint3 gridSizeLog2;
extern cudaExtent gVolumeExtent;
extern size_t gVolumeSize;


extern float gMinGreenIntensity;
extern float gMaxGreenIntensity;

extern uint gWidth;
extern uint gHeight;
extern dim3 gBlockSize;
extern dim3 gGridSize;

extern const int gcNumberFrame;
extern unsigned int gIdCurrentFrame;
extern unsigned long gIteration;
extern float3 gViewRotation;
extern float3 gViewTranslation;
extern float gInvViewMatrix[];
extern GLfloat  gNearFar[];

extern float gDensity;
extern float gBrightness;
extern float gTransferOffset;
extern float gTransferScale;
extern bool gLinearFiltering;

extern GLuint g_pbo;     // OpenGL pixel buffer object
extern GLuint g_tex;     // OpenGL texture object
extern struct cudaGraphicsResource *g_cuda_pbo_resource; // CUDA Graphics Resource (to transfer PBO)

extern StopWatchInterface *gTimer;

// Auto-Verification Code
extern const int gFrameCheckNumber;
extern int gFpsCount;        // FPS count for averaging
extern int gFpsLimit;        // FPS limit for sampling
extern int gIndex;
extern unsigned int gFrameCount;

extern int *pArgc;
extern char **pArgv;

extern int gButtonOx, gButtonOy;
extern int gButtonState;

extern float3 gBoxMin, gBoxMax;
extern float gVoxelLength;


extern float* g_array_perspective_fov;
extern float* g_array_perspective_eye_x;
extern float* g_array_perspective_eye_y;
extern float* g_array_perspective_eye_z;
extern float* g_array_perspective_center_x;
extern float* g_array_perspective_center_y;
extern float* g_array_perspective_center_z;
extern float* g_array_perspective_up_x;
extern float* g_array_perspective_up_y;
extern float* g_array_perspective_up_z;

extern float g_perspective_fov;
extern float g_perspective_eye_x;
extern float g_perspective_eye_y;
extern float g_perspective_eye_z;
extern float g_perspective_center_x;
extern float g_perspective_center_y;
extern float g_perspective_center_z;
extern float g_perspective_up_x;
extern float g_perspective_up_y;
extern float g_perspective_up_z;



extern const int gcNumberCamera;
extern int gIdCurrentCamera;


extern const char* gCTData;
extern const char* gBoundingBoxFilename;
extern const char* gMixingFluidBoundingBoxFilename;
extern const char* gPerspectiveFilename;
extern const char* gCameraParaMixingFluidFilename;
extern const char* gVisualHullSimulatedImageFilename;
extern const char* gVisualHullSimulatedColorTemperatureImageFilename;
extern const char* gVisualHullSimulatedTemperatureImageFilename;
extern const char* gVisualHullTagSmulatedFilename;
extern const char* gVisualHullTagSmulatedColorTemperatureFilename;
extern const char* gVisualHullTagSmulatedTemperatureFilename;
extern const char* gVisualHullImageFilename;
extern const char* gVisualHullMixingFluidImageFilename;
extern const char* gVisualHullSmokeImageFilename;
extern const char* gVisualHullTagFilename;
extern const char* gVisualHullMixingFluidTagFilename;
extern const char* gVisualHullTagSmokeFilename;
extern const char* gSingleSimulatedTemperatureFilename;
extern const char* gSimulatedCameraParameterFilename;
extern const char* gSmokeCameraParameterFilename;
extern const char* gCTCameraParamFilename;

extern const char* gSimulatedTemperatureImageNamePrefix;
extern const char* gSimulatedTemperatureResultImageNamePrefix;

extern const char* gCapturedSingleResultPath;
extern const char* gSmokeResultPath;

extern const char* gCapturedResultRedFilename;
extern const char* gCapturedResultGreenFilename;
extern const char* gCapturedResultBlueFilename;

extern const char* gSimulatedRedFilename;
extern const char* gSimulatedGreenFilename;
extern const char* gSimulatedBlueFilename;
extern const char* gSimulatedResultRedFilename;
extern const char* gSimulatedResultGreenFilename;
extern const char* gSimulatedResultBlueFilename;
extern const char* gSimulatedImageNamePrefix;
extern const char* gCTImageNamePrefix;
extern const char* gSimulatedImageNameColorTemperaturePrefix;
extern const char* gSimulatedResultImageNamePrefix;
extern const char* gCapturedResultImageNamePrefix;
extern const char* gSimulatedVolumeDataFilenamePrefix; 
extern const char* gSimulatedVolumeColorTemperatureFilenamePrefix;
extern const char* gSimulatedVolumeTemperatureFilenamePrefix;
extern const char* gSimulatedTemperatureResultVolumeDataFilename;

extern const char* gCapturedTemperatureResultImageNamePrefix;
extern const char* gCapturedTemperatureResultVolumeDataFilename;

extern const char* gSmokeResultImageNamePrefix;

extern const char* gMultipleSmokeVolumeDataPrefix;
extern const char* gMultipleSmokeImagePrefix;

extern const char* extrinsicParametersFilename;

extern char* gSourceImageData;
extern int gSourceImageWidthStep;
extern int gSourceImageNChannels;
extern int* integrogram;
extern int* d_source_imtegrogram;


struct ResizeImage {
	int width;
	int height;
	uchar *imageData;
};
extern ResizeImage *gResizeImageData_octree[20];

class Octree {
public:
	ushort min[3], len;
	ushort type = 1;
	bool isDet = false;
	__host__ __device__ void create(ushort a, ushort b, ushort c, ushort l, ushort t = 1) {
		min[0] = a;
		min[1] = b;
		min[2] = c;
		len = l;
		type = t;
		isDet = false;
	}
	__host__ __device__ void create(Octree t) {
		min[0] = t.min[0];
		min[1] = t.min[1];
		min[2] = t.min[2];
		len = t.len;
		type = t.type;
		isDet = false;
	}
	void display() {
		printf("min:%u %u %u len:%u isDet:%d type:%d\n", min[0], min[1], min[2], len,isDet,type);
	}
};
extern Octree *visual_hull_Octrees[100];
extern uint visual_hull_length[100];

class view_box {
public:
	double f[8][3];
	double o[3];
	double x, y, z;
	void create(double a[2], double b[2], double c[2]) {
		int t = 0;
		for (int i = 0; i < 2; i++) {
			for (int j = 0; j < 2; j++) {
				for (int k = 0; k < 2; k++) {
					f[t][0] = a[i];
					f[t][1] = b[j];
					f[t][2] = c[k];
					t++;
				}
			}
		}
		x = fabs(a[0] - a[1]);
		y = fabs(b[0] - b[1]);
		z = fabs(c[0] - c[1]);
		o[0] = a[0] > a[1] ? a[1] : a[0];
		o[1] = b[0] > b[1] ? b[1] : b[0];
		o[2] = c[0] > c[1] ? c[1] : c[0];
	};
	void getF(double f[8][3], int size) {
		double a[2], b[2], c[2];
		double _x, _y, _z;
		_x = x / size;
		_y = y / size;
		_z = z / size;
		a[0] = o[0];
		a[1] = a[0] + _x;
		b[0] = o[1];
		b[1] = b[0] + _y;
		c[0] = o[2];
		c[1] = c[0] + _z;
		int zz = 0;
		for (int i = 0; i < 2; i++) {
			for (int j = 0; j < 2; j++) {
				for (int k = 0; k < 2; k++) {
					f[zz][0] = a[i];
					f[zz][1] = b[j];
					f[zz][2] = c[k];
					zz++;
				}
			}
		}
	}
};
extern view_box visualHullBox;
class extrinsic_parameters {
public:
	double parameter_k[3][3];
	double parameter_r[3][3];
	double parameter_t[3];
	double parameter_m[3][4];
	void get_m() {
		for (int i = 0; i < 3; i++) {
			for (int j = 0; j < 3; j++) {
				parameter_m[i][j] = parameter_k[i][0] * parameter_r[0][j] + parameter_k[i][1] * parameter_r[1][j] + parameter_k[i][2] * parameter_r[2][j];
			}
			parameter_m[i][3] = parameter_k[i][0] * parameter_t[0] + parameter_k[i][1] * parameter_t[1] + parameter_k[i][2] * parameter_t[2];
		}
	};
	void print_m() {
		for (int i = 0; i < 3; i++) {
			for (int j = 0; j < 4; j++) {
				printf("%f ", parameter_m[i][j]);
			}
		}
		printf("\n");
	}
	void get_result(double *a, double *b, double x, double y, double z) {
		*a = parameter_m[0][0] * x + parameter_m[0][1] * y + parameter_m[0][2] * z + parameter_m[0][3] * 1;
		*b = parameter_m[1][0] * x + parameter_m[1][1] * y + parameter_m[1][2] * z + parameter_m[1][3] * 1;
		double c = parameter_m[2][0] * x + parameter_m[2][1] * y + parameter_m[2][2] * z + parameter_m[2][3] * 1;
		*a = *a / c;
		*b = *b / c;
	}
	__device__ void d_get_result(double *a, double *b, double x, double y, double z) {
		*a = parameter_m[0][0] * x + parameter_m[0][1] * y + parameter_m[0][2] * z + parameter_m[0][3] * 1;
		*b = parameter_m[1][0] * x + parameter_m[1][1] * y + parameter_m[1][2] * z + parameter_m[1][3] * 1;
		double c = parameter_m[2][0] * x + parameter_m[2][1] * y + parameter_m[2][2] * z + parameter_m[2][3] * 1;
		*a = *a / c;
		*b = *b / c;
	}
	__device__ void g_get_M_x_y(double *minX,double* maxX,double* minY, double* maxY, double f[8][3]) {
		*minX = *minY = 99999999;
		*maxX = *maxY = -1000000;
		double a, b;
		for (int i = 0; i < 8; i++) {
			d_get_result(&a, &b, f[i][0], f[i][1], f[i][2]);
			if (a > *maxX) {
				*maxX = a;
			}
			if (a < *minX) {
				*minX = a;
			}
			if (b > *maxY) {
				*maxY = b;
			}
			if (b < *minY) {
				*minY = b;
			}
		}
	}
	void get_M_x_y(double *minX, double* maxX, double* minY, double* maxY, double f[8][3]) {
		*minX = *minY = 99999999;
		*maxX = *maxY = -1000000;
		double a, b;
		for (int i = 0; i < 8; i++) {
			get_result(&a, &b, f[i][0], f[i][1], f[i][2]);
			if (a > *maxX) {
				*maxX = a;
			}
			if (a < *minX) {
				*minX = a;
			}
			if (b > *maxY) {
				*maxY = b;
			}
			if (b < *minY) {
				*minY = b;
			}
		}
	}
};
extern extrinsic_parameters* extrinsic_par;
extern extrinsic_parameters* d_extrinsic_par;
extern double bounding_box[3][2];


extern uchar* gVisualHullVertexTag;
extern uchar* gVisualHullTag;
extern VisualHullType* gCustomVisualHullTag;


// color reconstruction
extern float* gVolumeColor;
// for evaluation
extern float* gSrcVolumeColor;

extern uint* gOutput;

extern char* d_source_image_data;

extern float* d_volume_color;

extern VisualHullType* d_custom_type_visual_hull_tag;
extern uchar* d_visual_hull_tag;


extern std::ofstream gOutFilebRed;
extern std::ofstream gOutFilebGreen;
extern std::ofstream gOutFilebBlue;
extern std::ofstream gOutFileFlameVoxelIndex;
extern std::ofstream gOutFileARowIndex;
extern std::ofstream gOutFileARowPointer;
extern std::ofstream gOutFileAColumnIndex;
extern std::ofstream gOutFileAValue;
extern std::ofstream gOutFileRecPixelX;
extern std::ofstream gOutFileRecPixelY;
extern std::ofstream gOutFilePerCameraRecPixelSize;

extern const char* gAlgebraicbRedFile;
extern const char* gAlgebraicbGreenFile;
extern const char* gAlgebraicbBlueFile;
extern const char* gAlgebraicFlameVoxelIndexFile;
extern const char* gAlgebraicARowIndexFile;
extern const char* gAlgebraicARowPointerFile;
extern const char* gAlgebraicAColumnIndexFile;
extern const char* gAlgebraicAValueFile;
extern const char* gAlgebraicRecPixelXFile;
extern const char* gAlgebraicRecPixelYFile;
extern const char* gAlgebraicPerCameraRecPixelSizeFile;

extern const char* gSimulatedSinglePath;
extern const char* gAlgebraicSimulatedSinglePath;
extern const char* gVisualHullImageFile;
extern const char* gAlgebraicNumberFlamePerImageFile;
extern const char* gAlgebraicFlamePixelXFilePrefix;
extern const char* gAlgebraicFlamePixelYFilePrefix;
extern const char* gAlgebraicFlamePixelRedFilePrefix;
extern const char* gAlgebraicFlamePixelGreenFilePrefix;
extern const char* gAlgebraicFlamePixelBlueFilePrefix;
extern const char* gAlgebraicADimesionFile;

extern unsigned int gFlameVoxelSize;
extern unsigned int* d_flame_voxel_index;

extern uint gAnnz;
extern uint gAm;


extern std::ofstream evaluationOutput;
#endif	// _PARAMETERS_H_
